package lib

import (
    "strconv"
    "net/http"
    "encoding/json"
    "regexp"
    "os"
    "io/ioutil"
    "labix.org/v2/mgo"
    "labix.org/v2/mgo/bson"
    "time"
    "math/rand"
)


//一些重要配置
const ADMIN_USERNAME = "hmt"
const ADMIN_PASSWORD = "hmt2015"
const ADMIN_TOKEN = "fehfewhifbnewjhnfew"
const ADMIN_TOKEN_KEY = "signToken"
const MGO_DB = "127.0.0.1:27017"
const MGO_DB_NAME = "signTable"

/*
*处理静态资源访问
*
*/
func handleStatic(w http.ResponseWriter, r *http.Request) {
    url := r.URL.Path
    contentType := "text/plain"
    code := 200
    data := []byte("")
    
    fp, err := os.Open("." + url)
    defer fp.Close()
    
    if err == nil {
        data, _ = ioutil.ReadAll(fp)
    }else{
        code = 404
    }
    
    if len(regexp.MustCompile(`\.js$`).FindAllString(url, -1)) != 0{
        contentType = "text/js"
    }else  if len(regexp.MustCompile(`\.css$`).FindAllString(url, -1)) != 0{
        contentType = "text/css"
    }else  if len(regexp.MustCompile(`\.woff$`).FindAllString(url, -1)) != 0{
        contentType = "application/x-font-woff"
    }
    
    w.Header().Set("Content-Type", contentType)
    w.WriteHeader(code)
    w.Write(data)
}

//小朋友签到页面
func childrenUi(w http.ResponseWriter, r *http.Request){
    outputTemplateData(w, r, "childrenUi.html")
}

//拉取小朋友信息
func getChildrenMessage(w http.ResponseWriter,r *http.Request){
    
    studyNumber := r.FormValue("styudyNumber")
    
    obj := map[string]string{
        "message": "没有找到该学号用户信息！",
    }
    
    session, _ := mgo.Dial(MGO_DB)
    db := session.DB(MGO_DB_NAME)
    c := db.C("account")
    var children bson.M
    c.Find(bson.M{"studyNumber": studyNumber}).One(&children)
    if children != nil{
        obj["message"] = children["username"].(string) + "，" + children["sex"].(string) + "一枚"
    }
    
    data, _ := json.Marshal(obj)
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(200)
    w.Write(data)
}

//签到
func sign(w http.ResponseWriter,r *http.Request){
    
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(200)
    obj := map[string]interface{}{
        "code": 0,
    }
    
    //获取参数
    token := r.FormValue("token")
    code,_ := strconv.Atoi(r.FormValue("code"))
    studyNumber := r.FormValue("styudyNumber")
    
    var result bson.M
    session, _ := mgo.Dial(MGO_DB)
    db := session.DB(MGO_DB_NAME)
    c := db.C("signLog")
    
    //判断30分钟内有没有重复签到
    c.Find(bson.M{"token": token, "code": code, "studyNumber": studyNumber}).Sort("-createTime").One(&result)
    d, _ := time.ParseDuration("-0.5h")
    beforeTimes := time.Now().Add(d)
    var dd time.Time
    if result != nil{
        dd, _ = time.Parse("2006-01-02 15:04:05", result["createTime"].(string))
        beforeTimes, _ = time.Parse("2006-01-02 15:04:05", beforeTimes.Format("2006-01-02 15:04:05"))
    }
    
    if result != nil && dd.After(beforeTimes){
        //重复签到
        obj["code"] = 3
    }else{
        
        //判断签到码是否正确
        var signTableObj bson.M
        table := db.C("signTable")
        table.Find(bson.M{"token": token}).One(&signTableObj)
        if signTableObj == nil || signTableObj["code"].(int) != code{
            //签到码错误
            obj["code"] = 1
        }else {
            dd, _ = time.Parse("2006-01-02 15:04:05", signTableObj["expiredTime"].(string))
            dd2, _ := time.Parse("2006-01-02 15:04:05", time.Now().Format("2006-01-02 15:04:05"))
            
            if dd.Before(dd2){
                //签到已经过期
                obj["code"] = 2
            }else{
                //签到码正确
                obj["code"] = 0
                //保存签到数据
                c.Insert(bson.M{"studyNumber": studyNumber, "code": code, "token": token, "createTime": time.Now().Format("2006-01-02 15:04:05"), "type": "sign"})
            }
        }
        
    }
    
    html, _ := json.Marshal(obj)
    w.Write(html)
}


//签到后页面
func childrenSignUi(w http.ResponseWriter,r *http.Request){
    outputTemplateData(w, r, "childrenSignUi.html")
}

//后台主页
func admin(w http.ResponseWriter,r *http.Request){
    cookie, err := r.Cookie(ADMIN_TOKEN_KEY)
    
    if err == nil && cookie.Value == ADMIN_TOKEN{
        w.Header().Set("Location", "/admin/ui")
        w.WriteHeader(302)
    }
    
    outputTemplateData(w, r, "admin.html")
}

//后台登陆
func adminLogin(w http.ResponseWriter,r *http.Request){
    
    username := r.FormValue("username")
    password := r.FormValue("password")
    
    if ADMIN_USERNAME == username && ADMIN_PASSWORD == password{
        cookie := http.Cookie{Name: ADMIN_TOKEN_KEY, Value: ADMIN_TOKEN}
        http.SetCookie(w, &cookie)
    }
    
    w.Header().Set("Location", "/admin")
    w.WriteHeader(302)
}


//后台主页
func adminUi(w http.ResponseWriter,r *http.Request){
    outputTemplateData(w, r, "adminUi.html")
}

//添加签到表
func adminSignEdit(w http.ResponseWriter,r *http.Request){
    
    if r.Method == "GET"{
        outputTemplateData(w, r, "adminSignEdit.html")
    }else{
        w.Header().Set("Content-Type", "application/json")
        session, _ := mgo.Dial(MGO_DB)
        db := session.DB(MGO_DB_NAME)
        c := db.C("signTable")
        
        var result interface{}
        if r.FormValue("id") != "0"{
            c.Find(bson.M{"token": r.FormValue("id")}).One(&result)
        }else{
            result = nil            
        }

        var data []byte
        if result != nil{
            
            data, _ = json.Marshal(result)
        }else{
            data = []byte(`{"_id": null}`)
        }
        
        
        w.Write(data)
        
    }
    
}


//修改或添加签到表
func adminSignDoEdit(w http.ResponseWriter,r *http.Request){
    
    id := r.FormValue("id")
    title := r.FormValue("title")
    
    
    var result bson.M
    session, _ := mgo.Dial(MGO_DB)
    db := session.DB(MGO_DB_NAME)
    c := db.C("signTable")
    c.Find(bson.M{"token": id}).One(&result)
    
    if result == nil{
        //添加
        t := time.Now().Format("2006-01-02 15:04:05")
        objId := bson.NewObjectId()
        token := objId.Hex()
        data := bson.M{"_id": objId, "token": token, "title": title, "status": 0, "code": "", "expiredTime": t, "createTime": t}
        c.Insert(data)
    }else{
        //修改
        result["title"] = title
        c.Update(bson.M{"token":id}, result)
    }
    
    w.Header().Set("Location", "/admin/ui")
    w.WriteHeader(302)
}


//获取所有签到表
func getAllSignTables(w http.ResponseWriter,r *http.Request){
    
    var data []interface{}
    
    session, _ := mgo.Dial(MGO_DB)
    db := session.DB(MGO_DB_NAME)
    c := db.C("signTable")
    c.Find(bson.M{"status": 0}).Sort("-createTime").All(&data)
    
    var html []byte
    if data == nil{
        html = []byte("[]")
    }else{
        html, _ = json.Marshal(data)
    }
    
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(200)
    w.Write(html)
}


//删除签到表
func adminDeleteSignTable(w http.ResponseWriter,r *http.Request){
    
    session, _ := mgo.Dial(MGO_DB)
    db := session.DB(MGO_DB_NAME)
    c := db.C("signTable")
    var obj2 bson.M
    c.Find(bson.M{"token": r.FormValue("token")}).One(&obj2)
    if obj2 != nil{
        obj2["status"] = 1
        c.Update(bson.M{"token": r.FormValue("token")}, obj2)
    }
    w.Header().Set("Location", "/admin/ui")
    w.WriteHeader(302)
    w.Write([]byte("ok"))
}

//生成签到码
func adminBuildCode(w http.ResponseWriter,r *http.Request){
    
    rr := rand.New(rand.NewSource(time.Now().UnixNano()))
    n := rr.Intn(10000) % 10000
    for n < 1000{
        n = n *10
    }
    
    //获取30分钟后的时间
    d, _ := time.ParseDuration("0.5h")
    expiredTime := time.Now().Add(d).Format("2006-01-02 15:04:05")
    
    obj := map[string]interface{}{
        "code" : n,
        "expiredTime": expiredTime,
    }
    
    //修改记录
    session, _ := mgo.Dial(MGO_DB)
    db := session.DB(MGO_DB_NAME)
    c := db.C("signTable")
    var obj2 bson.M
    c.Find(bson.M{"token": r.FormValue("token")}).One(&obj2)
    if obj2 != nil{
        obj2["code"] = n
        obj2["expiredTime"] = expiredTime
        c.Update(bson.M{"token": r.FormValue("token")}, obj2)
    }
    
    html, _ := json.Marshal(obj)
    w.Header().Set("Content-Type", "application/json")
    w.Write(html)
}


//用户信息页面
func adminAccount(w http.ResponseWriter, r *http.Request){
    
    outputTemplateData(w, r, "adminAccount.html")
    
}


//保存用户信息
func adminAccountDoEdit(w http.ResponseWriter, r *http.Request){
    
    studyNumber := r.FormValue("studyNumber")
    username := r.FormValue("username")
    sex := r.FormValue("sex")
    work := r.FormValue("work")
    
    session, _ := mgo.Dial(MGO_DB)
    db := session.DB(MGO_DB_NAME)
    c := db.C("account")
    
    //先寻找熊孩子的信息在不在
    var children bson.M
    c.Find(bson.M{"studyNumber": studyNumber}).One(&children)
    
    if children != nil{
        children["studyNumber"] = studyNumber
        children["username"] = username
        children["sex"] = sex
        children["work"] = work
        c.Update(bson.M{"studyNumber": studyNumber}, children)
    }else{
        children = bson.M{
            "studyNumber": studyNumber,
            "username": username,
            "sex": sex,
            "work": work,
        }
        c.Insert(children)
    }
    
    w.Header().Set("Location", "/admin/account")
    w.WriteHeader(302)
}


//获取所有熊孩子的信息
func adminAllChildren(w http.ResponseWriter, r *http.Request){
    
    var childrens []bson.M
    session, _ := mgo.Dial(MGO_DB)
    db := session.DB(MGO_DB_NAME)
    c := db.C("account")
    c.Find(bson.M{}).Sort("studyNumber").All(&childrens)
    html, _ := json.Marshal(childrens)
    
   if string(html) == "null"{
       html = []byte("[]")
   }
    
    w.Header().Set("Content-Type", "application/json")
    w.Write(html)
    
}

//删除熊孩子信息
func adminRemoveChildrenData(w http.ResponseWriter, r *http.Request){
    
    studyNumber := r.FormValue("n")
    
    session, _ := mgo.Dial(MGO_DB)
    db := session.DB(MGO_DB_NAME)
    c := db.C("account")
    c.Remove(bson.M{"studyNumber": studyNumber})
    
    w.Header().Set("Location", "/admin/account")
    w.WriteHeader(302)
}


//主页
func handleIndex(w http.ResponseWriter, r *http.Request){
    outputTemplateData(w, r, "index.html")
}


//分析页面
func analy(w http.ResponseWriter, r *http.Request){
    
    if r.Method == "GET"{
        outputTemplateData(w, r, "analy.html")
        return
    }
    
    var logs []bson.M
    session, _ := mgo.Dial(MGO_DB)
    db := session.DB(MGO_DB_NAME)
    c := db.C("signLog")
    c.Find(bson.M{"token": r.FormValue("token")}).All(&logs)
    html, _ := json.Marshal(logs)
    
    if string(html) == "null"{
       html = []byte("[]")
   }
    
    w.Header().Set("Content-Type", "application/json")
    w.Write(html)
    
}